home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Imaging Engine / TextPrimitives.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  36.3 KB  |  1,292 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        TextPrimitives.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          This file contains routines necessary for
  6.                         translating text and glyph primitives into PostScript
  7.  
  8.      Version:    Technology:    Quickdraw GX 1.1.x
  9.       
  10.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  11. */
  12.  
  13. #include "GXToPSBuildConfig.h"
  14. #include <GXGraphics.h>
  15. #include "GXGraphicsPriv.h"
  16. #include <GXEnvironment.h>
  17. #include "GXToPostScript.h"
  18. #include "IOUtilities.h"
  19. #include "RDUtil.h"
  20. #include "FontHandler.h"
  21. #include "PublicPostScriptIE.h"
  22. #include "private.h"
  23. #include "PSIEResources.h"
  24. #include "GXErrors.h"
  25. #include "ShapeUtilities.h"
  26. #include <String.h>
  27.  
  28. #ifdef resumeLabel
  29.     #undef resumeLabel
  30. #endif
  31. #define resumeLabel(exception)
  32.  
  33.  
  34. #define kVerticalStyleMarkTag 'vsmk'
  35.  
  36. OSErr ResolveJustifiedText(TIEGlobalsHdl hIEGlobals, gxShape theShape, TGlyphDataRec *pGlyphData);
  37. OSErr ResolveJustifiedText(TIEGlobalsHdl hIEGlobals, gxShape theShape, TGlyphDataRec *pGlyphData)
  38. {
  39.         OSErr        status = noErr;
  40.         gxStyle shapeStyle = GXGetShapeStyle(theShape);
  41.         long i, counter;
  42.         Boolean allLeftJustified = true;
  43.         Boolean checkedShapeStyle = false;
  44.         gxPoint *positions;
  45.  
  46.     #pragma unused(hIEGlobals)
  47.  
  48.         /* walk through all the style runs, looking for some justification besides left */
  49.         for( i = 0; i < pGlyphData->nStyles; i++ ) {
  50.             gxStyle tempStyle;
  51.  
  52.             if( (tempStyle = pGlyphData->styles[i]) == nil ) {
  53.                 if( checkedShapeStyle )
  54.                     continue;
  55.                 tempStyle = shapeStyle;
  56.                 checkedShapeStyle = true;
  57.             }
  58.             if( GXGetStyleJustification(tempStyle) != gxLeftJustify ) {
  59.                 allLeftJustified = false;
  60.                 break;
  61.             }
  62.         }
  63.         if( allLeftJustified )
  64.             return noErr;
  65.  
  66.         if( pGlyphData->absPositions == nil ) {
  67.  
  68.             status = PrNewPtr((Ptr*)&positions, sizeof(gxPoint) * (pGlyphData->nChars + 1));
  69.             nrequire(status, failed_NewPtr);
  70.             GXGetGlyphMetrics(theShape, positions, nil, nil);
  71.  
  72.         } else {
  73.         
  74.             positions = pGlyphData->absPositions;
  75.             
  76.         }//end if
  77.  
  78.         /* copy the absolute positions into the regular positions and set all the advance bits to have absolute points */
  79.         BlockMove((Ptr)positions, (Ptr)pGlyphData->positions, pGlyphData->nChars * sizeof(gxPoint));
  80.         counter = pGlyphData->nChars >> 5;                            //This is the number of long words.
  81.         if( (counter << 5) < pGlyphData->nChars )                //make sure we didn't round down.
  82.             ++counter;
  83.         for( i = 0; i < counter; ++i ) {
  84.             pGlyphData->advanceBits[i] = 0xFFFFFFFF;
  85.         }
  86.         
  87.             if (positions != pGlyphData->absPositions)
  88.                 DisposePtr((Ptr)positions);
  89.  
  90. failed_NewPtr:
  91.         return (status);
  92. }
  93.  
  94. //<FF>
  95. /******************************************
  96.     ResolveVerticalText:
  97.     
  98.     Routine modifies the positions of any glyphs that
  99.     are in style runs that have the vertical-text bit
  100.     set so that those glyphs draw correctly in the 
  101.     horizontal-only model that PostScript uses.
  102.     
  103.     The data is modified in a glyph-data record that
  104.     has all of the glyph data previously loaded into it.
  105.  
  106. ******************************************/
  107. OSErr ResolveVerticalText(TIEGlobalsHdl hIEGlobals, gxShape theShape, TGlyphDataRec *pGlyphData);
  108. OSErr ResolveVerticalText(TIEGlobalsHdl hIEGlobals, gxShape theShape, TGlyphDataRec *pGlyphData)
  109.     {
  110.         OSErr                            status;
  111.         TIEGlobalsPtr         pGlobals;
  112.         gxShape                        shapeCopy;
  113.         long                            i, glyphCount;
  114.         unsigned long            *advLong, advMask;
  115.         register short        j;
  116.         long                            nChars;
  117.         gxTag                            changedTag;                        // We will tag styles we change so we know we changed them.
  118.         gxStyle                        *pStyle;                            // pointer to next style.
  119.         short                            *pRun;                                // Pointer to next run.
  120.         gxPoint                        *pPos;                                // Pointer to next position.
  121.         gxPoint                        *pAbsPos;                            // Pointer to next absolute position.
  122.         unsigned long            *newAdvBits;                    // New advance bits.
  123.         long                            workSize;                            // size of work space we will need.
  124.         long                            advSize;                            // Size of advance bits array of longs.
  125.         gxRectangle                *boxesH, *boxesV;            // Bounding boxes for vertical and horizontal cases.
  126.         gxRectangle                *pBoxH, *pBoxV;
  127.         gxPoint                        *absPositions;                // Absolute positions for glyphs.
  128.         gxTextAttribute        theAttributes;
  129.  
  130.         /** First do a quick check to see if there are any vertical runs **/
  131.         
  132.         pStyle = pGlyphData->styles;
  133.         for (i = pGlyphData->nStyles - 1 ; i >= 0; --i) {
  134.         
  135.             if( *pStyle && (GXGetStyleTextAttributes(*pStyle) & gxVerticalText) )
  136.                 break;
  137.             else if ((*pStyle == nil) && (GXGetStyleTextAttributes(GXGetShapeStyle(theShape)) & gxVerticalText))
  138.                 break;
  139.                 
  140.             pStyle++;
  141.         
  142.         }//end for
  143.         
  144.         if (i == -1)                            // no vertical style runs, just get out of here.
  145.             return(noErr);
  146.  
  147.         /*** There was at least one vertical style!  Resovle positions ***/
  148.         
  149.         nChars = pGlyphData->nChars;
  150.                 
  151.         /******
  152.             First allocate all the memory we will need:
  153.             for 2 sets of bounding boxes, advance bits, and, if we don't
  154.             already have them, the absolute positions for each
  155.             glyph.
  156.         ****/
  157.         workSize = nChars * 2 * sizeof(gxRectangle);            // room for bounding boxes.
  158.  
  159.         advSize = pGlyphData->nChars >> 5;                            //This is the number of long words.
  160.         if ((advSize << 5) < pGlyphData->nChars)                //make sure we didn't round down.
  161.             advSize++;
  162.         workSize += sizeof(long) * advSize;
  163.         
  164.         if (pGlyphData->absPositions == nil)    
  165.             workSize += (nChars + 1) * sizeof(gxPoint);                    // For absolute positions.
  166.         else
  167.             absPositions = pGlyphData->absPositions;
  168.         
  169.         nrequire(status = PSSetWorkSpaceSize(hIEGlobals, workSize), failed_SetSize);
  170.  
  171.         pGlobals = *hIEGlobals;
  172.         HLock(pGlobals->hWorkSpace);                                // We will be buffering this data so lock it.
  173.         
  174.         /** Point at the workspace **/
  175.         {
  176.             Ptr p = *(pGlobals->hWorkSpace);
  177.             
  178.             boxesH = (gxRectangle*)p;
  179.             p += nChars * sizeof(gxRectangle);
  180.             
  181.             boxesV = (gxRectangle*)p;
  182.             p += nChars * sizeof(gxRectangle);
  183.             
  184.             newAdvBits = (unsigned long*)p;
  185.             p += advSize * sizeof(unsigned long);
  186.             
  187.             /* Set the advance bits to 1 */
  188.             advLong = newAdvBits;
  189.             for (i = 0; i < advSize; ++i)
  190.                 *advLong++ = 0xFFFFFFFF;
  191.             
  192.             if (pGlyphData->absPositions == nil) {
  193.             
  194.                 absPositions = (gxPoint*)p;
  195.                 GXGetGlyphMetrics(theShape, absPositions, boxesV, nil);
  196.                 
  197.             } else {
  198.             
  199.                 GXGetGlyphMetrics(theShape, nil, boxesV, nil);                // already got positions in GlyphDataIntoWorkSpace
  200.             
  201.             }//end if
  202.             
  203.         }//end block
  204.         
  205.         /****
  206.             Now turn off vertical bit for all style runs that have it to get other bounding boxes,
  207.                 tag the styles we changed.
  208.                                 
  209.         ****/
  210.         changedTag = GXNewTag(kVerticalStyleMarkTag, 0, nil);                // Make a tag to mark styles with.
  211.         
  212.         pStyle = pGlyphData->styles;
  213.         for (i = pGlyphData->nStyles - 1 ; i >= 0; --i) {
  214.         
  215.             theAttributes = GXGetStyleTextAttributes(*pStyle);
  216.         
  217.             if (theAttributes & gxVerticalText) {
  218.             
  219.                 theAttributes &= ~gxVerticalText;
  220.                 GXSetStyleTags(*pStyle, kVerticalStyleMarkTag, 0, 0, 1, &changedTag);
  221.  
  222.                 GXSetStyleTextAttributes(*pStyle, theAttributes);
  223.                 
  224.             }//end if
  225.             
  226.             ++pStyle;
  227.             
  228.         }//end for
  229.         
  230.         GXDisposeTag(changedTag);
  231.         
  232.  
  233.         /**** 
  234.             Now get the bounding boxes for the non-vertical glyphs:
  235.                 1. Make a copy of the shape so we don't corrupt it.
  236.                 2. Make this version have absolute positions for all glyphs
  237.                 3. Get the bounding boxes
  238.         ****/
  239.  
  240.         shapeCopy = GXCopyToShape(nil, theShape);
  241.         GXSetGlyphs(shapeCopy, nil, nil, absPositions, (long*)newAdvBits, nil, nil, nil);        // we need to use absolute positions for each glyph to get correct metrics.
  242.         GXChangedShape(shapeCopy);
  243.         GXGetGlyphMetrics(shapeCopy, nil, boxesH, nil);
  244.         GXDisposeShape(shapeCopy);
  245.         nrequire(status = GXGetGraphicsError(nil), failed_CopyIt);
  246.                 
  247.         /***
  248.             Now we have bounding boxes for the vertical case as well as the horizontal case:
  249.         
  250.             Modify the positions by the difference between the vertical box location (top, left)
  251.             and the horizontal box location.        
  252.         ***/
  253.         pRun = pGlyphData->runs;
  254.         pPos = pGlyphData->positions;
  255.         pAbsPos = absPositions;
  256.         pBoxH = boxesH;
  257.         pBoxV = boxesV;
  258.         pStyle = pGlyphData->styles;
  259.         glyphCount = 0;
  260.         for (i = 1; i <= pGlyphData->nStyles; ++i) {
  261.         
  262.             
  263.             if (GXGetStyleTags(*pStyle, kVerticalStyleMarkTag, 1, gxSelectToEnd, nil) ) {
  264.             
  265.                 theAttributes = GXGetStyleTextAttributes(*pStyle);
  266.                 GXSetStyleTextAttributes(*pStyle, theAttributes | gxVerticalText);            // put it back to be clean.
  267.                 
  268.                 j = glyphCount / 32;                                                        // Get offset into advance array.
  269.                 advLong = pGlyphData->advanceBits + j;                    // Get address of advance bits.
  270.                 advMask = 0x80000000U >> (glyphCount - j*32);        // Offset mask for remainder.
  271.  
  272.  
  273.                 /** Modify positions for this run and set each advance bit **/
  274.                 
  275.                 for (j = *pRun - 1; j >= 0; --j) {
  276.                                 
  277.                     pAbsPos->x -= (pBoxH->left - pBoxV->left);
  278.                     pAbsPos->y -= (pBoxH->top - pBoxV->top);
  279.                     
  280.                     pPos->x = pAbsPos->x;
  281.                     pPos->y = pAbsPos->y;
  282.                     
  283.                     /** Set the advance bit for this glyph **/
  284.                     
  285.                     *advLong |= advMask;
  286.                     if ((advMask >>= 1) == 0) {
  287.                     
  288.                         ++advLong;
  289.                         advMask = 0x80000000;
  290.                     
  291.                     }//end if
  292.                                         
  293.                     ++pAbsPos;
  294.                     ++pPos;
  295.                     ++pBoxV;
  296.                     ++pBoxH;
  297.                 
  298.                 }//end for
  299.                 
  300.                 /** Make sure the glyph immediately following this run also has absolute position **/
  301.                 
  302.                 if (i < pGlyphData->nStyles) {                // don't do it for the last style run.
  303.                 
  304.                     *advLong |= advMask;
  305.                     pPos->x = pAbsPos->x;
  306.                     pPos->y = pAbsPos->y;
  307.                 
  308.                 }//end if
  309.                 
  310.             
  311.             } else {
  312.             
  313.                 pAbsPos += *pRun;
  314.                 pPos += *pRun;
  315.                 pBoxH += *pRun;
  316.                 pBoxV += *pRun;
  317.             
  318.             }//end if
  319.             
  320.             glyphCount += *pRun;
  321.             
  322.             ++pStyle;
  323.             ++pRun;
  324.         
  325.         }//end for
  326.  
  327. failed_CopyIt:
  328.  
  329.         status = PSReleaseWorkSpace(hIEGlobals);
  330.         ncheck(status);
  331.  
  332. failed_SetSize:    
  333.         return(status);
  334.         
  335.     }//ResolveVerticalText
  336.  
  337.  
  338.  
  339.  
  340.  
  341.  
  342. //<FF>
  343. /******************************************
  344.     GlyphDataIntoWorkSpace:
  345.     
  346.     Function loads data from the Glyph Shape
  347.     into specified parameter block (which really will point
  348.     into the workspace), the workspace is locked upon 
  349.     successful completion of this routine.
  350.     
  351.     The client must call PSReleaseWorkSpace when done
  352.     with the glyph data.
  353.     
  354. ********************************************/
  355. OSErr GlyphDataIntoWorkSpace(TIEGlobalsHdl hIEGlobals, gxShape theShape, TGlyphDataRec *pGlyphData);
  356. OSErr GlyphDataIntoWorkSpace(TIEGlobalsHdl hIEGlobals, gxShape theShape, TGlyphDataRec *pGlyphData)
  357.     {
  358.         OSErr                    status;
  359.         long                    totalSize;
  360.         long                    size;
  361.         gxTag                    fhGlyphTag;
  362.         gxTag                    fh2byteTag;
  363.         TIEGlobalsPtr    pGlobals;
  364.         Ptr                        p;
  365.         
  366.  
  367.         /* Get the tag containing modified glyph code data */
  368.         
  369.         GXGetShapeTags(theShape, fhTextDataTag, 1, 1, &fhGlyphTag);
  370.         pGlyphData->byteCount = GXGetTag(fhGlyphTag, nil, nil);
  371.         
  372.         /** Get statistics on the glyph shape **/
  373.         
  374.         GXGetGlyphs(theShape, &(pGlyphData->nChars), nil, nil, nil, nil, &(pGlyphData->nStyles), nil, nil);
  375.         
  376.         /** Space needed for Font Handleur 8/16 data **/
  377.         if (GXGetShapeTags(theShape, fh1or2byteTag, 1, 1, nil) ) {
  378.         
  379.             GXGetShapeTags(theShape, fh1or2byteTag, 1, 1, &fh2byteTag);
  380.             pGlyphData->fhUserDataSize = GXGetTag(fh2byteTag, nil, nil);
  381.         
  382.         } else {
  383.         
  384.             pGlyphData->fhUserDataSize = 0;
  385.             
  386.         }//end if
  387.         
  388.         /** Compute the total work space size we will need **/
  389.         totalSize = pGlyphData->byteCount;        
  390.         totalSize += pGlyphData->nChars * (    sizeof(gxPoint) +                //the positions 
  391.                                                                                 sizeof(gxPoint) +                //the tangents
  392.                                                                                 sizeof(short));                    //the glyphs
  393.                                                         
  394.         totalSize += pGlyphData->nStyles * (    sizeof(gxStyle)    +            //the styles
  395.                                                                                     sizeof(short) );            //the style runs    
  396.         
  397.         totalSize += pGlyphData->fhUserDataSize;
  398.         
  399.         
  400.         /** For level-2, we need absolute positions for every glyph in case we must use xyshow **/
  401.                 
  402.         if ((*hIEGlobals)->params.languageLevel > 1)
  403.             totalSize += (pGlyphData->nChars + 1) * sizeof(gxPoint);        
  404.         
  405.         /* Compute the space needed for the advance bits */
  406.         size = pGlyphData->nChars >> 5;                            //This is the number of long words.
  407.         if ((size << 5) < pGlyphData->nChars)                //make sure we didn't round down.
  408.             size++;
  409.         totalSize += sizeof(long) * size;
  410.     
  411.         nrequire(status = PSSetWorkSpaceSize(hIEGlobals, totalSize), failed_SetSize);
  412.  
  413.         pGlobals = *hIEGlobals;
  414.         HLock(pGlobals->hWorkSpace);                                // We will be buffering this data so lock it.
  415.         
  416.         /** Now point the fields of the glyph param block into the work space **/
  417.  
  418.         p = *(pGlobals->hWorkSpace);
  419.         
  420.         pGlyphData->positions = (gxPoint*)p;
  421.         p += pGlyphData->nChars * sizeof(gxPoint);
  422.         
  423.         pGlyphData->tangents = (gxPoint*)p;
  424.         p += pGlyphData->nChars * sizeof(gxPoint);
  425.         
  426.         pGlyphData->advanceBits = (unsigned long*)p;
  427.         p += size * sizeof(long);
  428.         
  429.         pGlyphData->styles = (gxStyle*)p;
  430.         p += pGlyphData->nStyles * sizeof(gxStyle);
  431.         
  432.         pGlyphData->glyphs = (unsigned char*)p;
  433.         p += pGlyphData->nChars * sizeof(short);
  434.         
  435.         pGlyphData->runs = (short*)p;
  436.         p += pGlyphData->nStyles * sizeof(short);
  437.         
  438.         pGlyphData->text8 = p;
  439.         p += pGlyphData->byteCount;
  440.         
  441.         pGlyphData->fhUserData = (unsigned long*)p;
  442.         p += pGlyphData->fhUserDataSize;
  443.         
  444.         pGlyphData->absPositions = (gxPoint*)p;
  445.         
  446.         GXGetGlyphs(theShape, nil, 
  447.                                                     nil,                                                    // glyph code data comes from font handler tag
  448.                                                     pGlyphData->positions,
  449.                                                     (long*)(pGlyphData->advanceBits),
  450.                                                     pGlyphData->tangents,
  451.                                                     nil,
  452.                                                     pGlyphData->runs,
  453.                                                     pGlyphData->styles);
  454.         
  455.         
  456.         GXGetTag(fhGlyphTag, nil, pGlyphData->glyphs);        // get resolved bytes.
  457.         
  458.         if (pGlyphData->fhUserDataSize > 0)                            // get 2 byte tag, if it is there.
  459.             GXGetTag(fh2byteTag, nil, pGlyphData->fhUserData);
  460.         
  461.         /** We always need absolute positions for level 2 **/
  462.         if (pGlobals->params.languageLevel > 1)
  463.             GXGetGlyphMetrics(theShape, pGlyphData->absPositions, nil, nil);
  464.         else
  465.             pGlyphData->absPositions = nil;
  466.         
  467.         nrequire(status = GXGetGraphicsError(nil), failed_GetGlyphs);
  468.         
  469.         if (pGlyphData->styles[0] == nil) {
  470.         
  471.             pGlyphData->styles[0] = GXGetShapeStyle(theShape);
  472.  
  473.         }//end if        
  474.         
  475.         /* fix the non-left justified positions */
  476.         nrequire(status = ResolveJustifiedText(hIEGlobals, theShape, pGlyphData), failed_ResolveJustification);
  477.  
  478.  
  479.         /*** Fix vertical style runs positions ***/
  480.         
  481.         nrequire(status = ResolveVerticalText(hIEGlobals, theShape, pGlyphData), failed_Vertical);
  482.         
  483.         
  484.         return(status);
  485.  
  486. failed_Vertical:
  487. failed_ResolveJustification:
  488. failed_GetGlyphs:
  489.         {
  490.             OSErr        saveStatus = PSReleaseWorkSpace(hIEGlobals);
  491.             ncheck(saveStatus);
  492.             
  493.         }
  494.  
  495. failed_SetSize:
  496.         return(status);
  497.  
  498.     }//GlyphDataIntoWorkSpace
  499.     
  500.  
  501. //<FF>
  502. #ifdef testappOLDFONTHANDLER
  503.     
  504.     
  505. extern    TIEGlobalsHdl gGlobalHdl;
  506.     
  507.     
  508.         OSErr FHeurFontAvailable(
  509.                                     TFontStatistics     fDbaseHdl,
  510.                                     gxStyle                        theStyle,
  511.                                     char*                            name,
  512.                                     long                            *child,
  513.                                     TMemoryManageResult    *memoryState
  514.                                 )
  515.             {
  516.             
  517.                 font            theFont;
  518.             
  519.                 *child = 0;
  520.                 theFont = GetStyleFont(theStyle);
  521.                 
  522.                 name[0] = FindFontName(theFont, postscriptFontName, macintoshPlatform, romanScript, englishLanguage,
  523.                                             &name[1], nil);
  524.                                             
  525.                 /** Make it into a Pascal string **/
  526.  
  527.                 return(noErr);
  528.             }
  529.         
  530.         OSErr FHeurBalanceSaveLevel(
  531.                                     TFontStatistics         fDbaseHdl,
  532.                                     TMemoryManageResult        *memoryState
  533.                                 )
  534.             {
  535.                 return(noErr);
  536.             }
  537.  
  538.         OSErr FHeurResolveShapeFonts(TFontStatistics     fDbaseHdl, gxShape *theShape)
  539.             {
  540.                 OSErr                        status;
  541.                 TGlyphDataRec        glyphData;                    // Block o'glyph data.
  542.                 long                        currGlyph;                    // Index of glyph we are currently processing.
  543.                 long                        styleIndex;                    // Index of style we are currently processing.
  544.                 Ptr                            p1, p2;
  545.                 short                        *glyph;
  546.                 short                        i,j,k,idx;
  547.                 gxTag                        textTag;
  548.                 long                        pltfrm;
  549.                 long                        size;
  550.                 
  551.                 shapeType             theType = GetShapeType(*theShape);
  552.                 
  553.                 
  554.                 if (theType == layoutType) {
  555.                     SetShapeType(*theShape, glyphType);
  556.                     theType = glyphType;
  557.                 }//end if
  558.                     
  559.                 if (theType == textType) {
  560.                     
  561.                     long            nBytes;
  562.                     
  563.                     GetText(*theShape, &nBytes, nil, nil);
  564.  
  565.                     status = PSSetWorkSpaceSize(gGlobalHdl, nBytes);
  566.                     nrequire(status, failed_Text);
  567.                     
  568.                     p1 = *(*gGlobalHdl)->hWorkSpace;
  569.                     GetText(*theShape, nil, p1, nil);
  570.                     
  571.                     textTag = NewTag(kResolveFontTextDataTag, nBytes, p1);
  572.                     
  573.                     SetShapeTags(*theShape, kResolveFontTextDataTag, 1, 0, 1, &textTag);
  574.  
  575.                     PSReleaseWorkSpace(gGlobalHdl);
  576.                     
  577.                     //DisposeTag(textTag);
  578.  
  579. failed_Text:
  580.                     return(status);
  581.                     
  582.                 }//end if
  583.                 
  584.                 /** Set up the work space for processing the glyphs **/
  585.         
  586.         
  587.                 size = GetGlyphs(*theShape, &glyphData.nChars, nil, nil, nil, nil, &glyphData.nStyles, nil, nil);
  588.                 
  589.                 size += glyphData.nChars +                                            // 8 bit text
  590.                                  glyphData.nStyles * sizeof(gxStyle) +        // styles;
  591.                                 glyphData.nStyles * sizeof(short);            // style runs;
  592.                 
  593.                 status = PSSetWorkSpaceSize(gGlobalHdl, size);
  594.                 nrequire(status, failed_GetGlypData);
  595.                 
  596.                 p1 = *(*gGlobalHdl)->hWorkSpace;
  597.                 
  598.                 glyphData.text8 = p1;
  599.                 p1 += glyphData.nChars;
  600.                 
  601.                 glyphData.runs = (short*)p1;
  602.                 p1 += glyphData.nStyles * sizeof(short);
  603.                 
  604.                 glyphData.styles = (gxStyle*)p1;
  605.                 p1 += glyphData.nStyles * sizeof(gxStyle);
  606.                 
  607.                 glyphData.glyphs = p1;
  608.                 
  609.                 GetGlyphs(*theShape, nil, glyphData.glyphs, nil, nil, nil, nil, glyphData.runs, glyphData.styles);
  610.                 
  611.                 j = 0;
  612.                 p1 = glyphData.text8;
  613.                 p2 = (Ptr)glyphData.glyphs;
  614.  
  615.                 for (i = 0; i < glyphData.nStyles; i++) {
  616.                 
  617.                     if (glyphData.styles[i] == 0)
  618.                         glyphData.styles[i] = GetShapeStyle(*theShape);
  619.                 
  620.                     k = glyphData.runs[i];
  621.                     
  622.                     pltfrm = GetStylePlatform(glyphData.styles[i], nil, nil);
  623.                     dprintf(notrace, "Platform: %d", pltfrm);
  624.                     
  625.                     if ((pltfrm == macintoshPlatform) && !(GetShapeAttributes(*theShape) & ignorePlatformShape)) {
  626.                         
  627.                         
  628.                         for (idx = 0; idx < k; idx++)
  629.                             *p1++ = *p2++;
  630.                     
  631.                     } else {
  632.                     
  633.                         glyph = (short*)p2;
  634.                         for (idx = 0; idx < k; idx++) {
  635.                         
  636.                             *p1 = (char)(*glyph++  + 0x1D) ;
  637.                             if (*p1 > 0x7F)
  638.                                 ++(*p1);
  639.                             
  640.                             ++p1;
  641.                         
  642.                         }//end for
  643.                         p2 += 2 * k;
  644.                     
  645.                     }//end if
  646.                 
  647.                 }//end for
  648.                 
  649.                 textTag = NewTag(kResolveFontTextDataTag, glyphData.nChars, glyphData.text8);
  650.                 
  651.                 SetShapeTags(*theShape, kResolveFontTextDataTag, 1, 0, 1, &textTag);
  652.                 
  653.                 dprintf(notrace, "Address is: %X %X", glyphData.text8, glyphData.glyphs);
  654.                 
  655.                 //DisposeTag(textTag);
  656.  
  657.                 ncheck(GetGraphicsError(nil));
  658.                 
  659.                 status = PSReleaseWorkSpace(gGlobalHdl);
  660.                 ncheck(status);
  661.                 
  662.         failed_GetGlypData:
  663.                 return(status);
  664.             }
  665. #endif
  666.  
  667.  
  668.  
  669. //<FF>
  670. /*********************************************
  671.     AnalyzeGlyphPositions:
  672.     
  673.     Routine analyzes an array of positions to
  674.     determine if they are vertical, horizontal, all equal,
  675.     or all different.
  676.     
  677.         positions:            pointer to the array of positions to analyze.
  678.         n:                            Number of positions to analyze.
  679.         returned:                the positions bias.    
  680.  
  681. **********************************************/
  682. TGlyphPosBias AnalyzeGlyphPositions(register gxPoint *positions, register short n);
  683. TGlyphPosBias AnalyzeGlyphPositions(register gxPoint *positions, register short n)
  684.     {
  685.         gxPoint                firstPoint;
  686.         Boolean                allHorizontal, allVertical;
  687.         
  688.         #ifdef wierdTiming
  689.         if (true)
  690.             return(eAllEqual);
  691.         #endif
  692.         
  693.         firstPoint = positions[0];
  694.         allVertical = true;
  695.         allHorizontal = true;
  696.         
  697.         for (--n; n >= 0; --n) {
  698.         
  699.             if (firstPoint.x != positions->x)
  700.                 allVertical = false;
  701.                 
  702.             if (firstPoint.y != positions->y)
  703.                 allHorizontal = false;
  704.                 
  705.             /** If allVertical and allHorizontal both go to false, then we know it's mixed so break out **/
  706.             if (!allVertical && !allHorizontal)
  707.                 break;
  708.             
  709.             ++positions;
  710.         
  711.         }//end for
  712.         
  713.         if (allVertical && allHorizontal)
  714.             return(eAllEqual);
  715.             
  716.         else if (allVertical)
  717.             return(eAllVertical);
  718.             
  719.         else if (allHorizontal)
  720.             return(eAllHorizontal);
  721.             
  722.         else
  723.             return(eMixed);
  724.         
  725.     }//AnalyzeGlyphPositions
  726.  
  727.  
  728.  
  729.  
  730.  
  731. //<FF>
  732. /*******************************************
  733.     ProcessGlyphGroupDelta:
  734.     
  735.     Routine translates a glyph group with advance
  736.     bits specifying deltas for each character advance
  737.     to PostScript.
  738.     
  739.     nGlyphs:            How many glyphs in the group.
  740.     deltas:                Array of deltas for the glyphs.
  741.     text8:                Pointer to the 8 bit data for the group.
  742.     byteCount:        Number of bytes in the 8-bit data.
  743.     rdParams:            pointer to the RDUtil parameter block.
  744.     addToIndex:        0 for normal, kAddForHexText for text as hex.
  745.  
  746. *********************************************/
  747. OSErr ProcessGlyphGroupDelta(short nGlyphs, gxPoint *deltas, char *text8, 
  748.                                 long byteCount, TRDParams *rdParams, TGlyphPosBias theBias, 
  749.                                 long addToIndex);
  750. OSErr ProcessGlyphGroupDelta(short nGlyphs, gxPoint *deltas, char *text8, 
  751.                                 long byteCount, TRDParams *rdParams, TGlyphPosBias theBias, 
  752.                                 long addToIndex)
  753.     {
  754.         OSErr                        status;
  755.         gxPoint*                pPoint;
  756.         register short    j;
  757.                 
  758.         /** Get pen in correct position for 1st glyph in group. **/
  759.         
  760.         if ((deltas[0].x != 0) | (deltas[0].y != 0)) {
  761.         
  762.             status = DoRmoveto(rdParams, &(deltas[0]));
  763.             nrequire(status, failed_Output);
  764.             
  765.         }//end if
  766.  
  767.         /*** Draw the glyphs ****/
  768.         
  769.         if (theBias == eAllEqual) {
  770.         
  771.             if ((deltas[1].x == 0) && (deltas[1].y == 0)) {                    //if deltas are zero, just do show.
  772.             
  773.                 rdParams->resIndex = addToIndex +  kShow;
  774.                 
  775.             }    else {                                                                                                //If they are all equal, do ashow.
  776.                 
  777.                 nrequire(status = DoPoint(rdParams, &(deltas[1])), failed_Output);        //    Output the delta.
  778.                 rdParams->resIndex = addToIndex +  kAshow;
  779.             
  780.             }//end if
  781.         
  782.         } else {                                    // do kshow with rmoveto's.
  783.         
  784.             pPoint = deltas + nGlyphs - 1;
  785.  
  786.             if (theBias == eAllHorizontal) {
  787.             
  788.                 rdParams->resIndex = kDoFixed;
  789.                 for (j = nGlyphs-2; j >= 0; --j) {                    // Do all X's but the first point, first was handled by rmoveto
  790.                         
  791.                     nrequire(status = RDResPrintf(rdParams, pPoint->x), failed_Output);
  792.                     --pPoint;
  793.                         
  794.                 }//end for
  795.                 
  796.                 nrequire(status = RDResPrintf(rdParams, deltas[1].y), failed_Output);                // Output the constant Y value on the stack.(y[1])
  797.                 rdParams->resIndex = addToIndex +  kKshowRH;
  798.             
  799.             } else if (theBias == eAllVertical) {
  800.  
  801.                 rdParams->resIndex = kDoFixed;
  802.                 for (j = nGlyphs-2; j >= 0; --j) {                    // Do all Y's but the first point, first was handled by rmoveto
  803.                         
  804.                     nrequire(status = RDResPrintf(rdParams, pPoint->y), failed_Output);
  805.                     --pPoint;
  806.                         
  807.                 }//end for
  808.                 
  809.                 nrequire(status = RDResPrintf(rdParams, deltas[1].x), failed_Output);                    // Output the constant X value on the stack. (x[1])
  810.                 rdParams->resIndex = addToIndex +  kKshowRV;
  811.  
  812.             } else {
  813.                 
  814.                 rdParams->resIndex = kDoPoint;
  815.                 for (j = nGlyphs-2; j >= 0; --j) {                    // Do all but the first point.
  816.                         
  817.                     nrequire(status = RDResPrintf(rdParams, pPoint), failed_Output);
  818.                     --pPoint;
  819.                         
  820.                 }//end for
  821.                 
  822.                 rdParams->resIndex = addToIndex +  kKshowR;
  823.  
  824.             }//end if
  825.             
  826.         
  827.         }//end if
  828.     
  829.         //Output the string using whichever script procedure set above in rdParams->resIndex
  830.         
  831.         status = RDResPrintf(rdParams, text8, byteCount);
  832.         ncheck(status);
  833.     
  834. failed_Output:
  835.         return(status);
  836.     
  837.     }//ProcessGlyphGroupDelta
  838.  
  839.  
  840. //<FF>
  841. /*******************************************
  842.     ProcessStyleRun:
  843.     
  844.     Routine translates a style run from a glyph shape into PostScript
  845.     
  846.     hIEGlobals:                    the Global storage handle.
  847.     startGlyph:                    Index of the first glyph in the style run.
  848.     theStyle:                        style of style run to process.
  849.     glyphData:                    Pointer to the glyph data block.
  850.     runLength:                    Number of glyphs in style/tangent run.
  851.     pTangent:                        tangent vector for this run.
  852.     addToIndex:                    0 for normal, kAddForHexText for text as hex.
  853.     
  854. *********************************************/
  855. OSErr ProcessStyleRun(TIEGlobalsHdl hIEGlobals, short startGlyph, gxStyle theStyle,
  856.                                                 TGlyphDataRec *glyphData, short runLength, gxPoint* pTangent,
  857.                                                 long addToIndex);
  858. OSErr ProcessStyleRun(TIEGlobalsHdl hIEGlobals, short startGlyph, gxStyle theStyle,
  859.                                                 TGlyphDataRec *glyphData, short runLength, gxPoint* pTangent,
  860.                                                 long addToIndex)
  861.     {
  862.         OSErr                                        status;    
  863.         TRDParams                                *rdParams;
  864.         register unsigned long    *advLong;
  865.         register unsigned long    advMask;
  866.         long                                        i;
  867.         long                                        firstGlyphInGroup;        // Index of first glyph in the group.
  868.         long                                        groupLength;                    // size of a glyph group (all adv bits the same)
  869.         Boolean                                    advIsOne;                            // True if current advance bit is one.
  870.         Boolean                                    currAdv;
  871.         char                                        *text8;                                // Pointer to the 8-bit data.
  872.         long                                        byteCount;                        // Number of bytes in the 8-bit datay.
  873.         gxPoint*                                posGroup;                            // pointer into positions for group.
  874.         TGlyphPosBias                        theBias;                            // Bias for the glyph positions.
  875.         gxPoint                                    nextDelta;                        // delta of first glyph of next run
  876.         
  877.         rdParams = (*hIEGlobals)->pRDParams;
  878.         advLong = glyphData->advLong;
  879.         advMask = glyphData->advMask;
  880.                         
  881.         /** Set up text style in graphics state **/
  882.  
  883.         status = _TextStylePrimitive(hIEGlobals, theStyle, pTangent);
  884.         nrequire(status, failed_Font);
  885.         
  886.         /*******************************
  887.             Find all of the glyph groups in the style run
  888.             and output them.  A glyph group is a run of
  889.             glyphs that have the same advance bit value
  890.         ********************************/
  891.         firstGlyphInGroup = startGlyph;
  892.         NEXTBIT(advIsOne, advLong, advMask);                // Find out if the 1st advance is 1 or zero.
  893.         i = 0;
  894.         
  895.         while(i < runLength) {
  896.         
  897.             groupLength = 1;                                                    // Group length is one glyph so far.
  898.             while ( ++i < runLength) {                                // ++i, we're about to look at next glyph's bit.
  899.             
  900.                 NEXTBIT(currAdv, advLong, advMask);            // Get the next advance bit value.
  901.                 if (currAdv != advIsOne)                                // Break out of loop if adv bit is different.
  902.                     break;
  903.                     
  904.                 ++groupLength;                                                    // If we didn't fall out yet, grow group.
  905.                 
  906.             }//while
  907.             
  908.             /********************
  909.                 Find out how many bytes are necessary for this run.  For 8-bit text it will
  910.                 be the same as groupLength.
  911.             *********************/            
  912.             text8 = (char*)(glyphData->currByte);
  913.             if (glyphData->fhUserDataSize == 0) {
  914.             
  915.                 byteCount = groupLength;
  916.                 
  917.             } else {                                                                        // Traverse the bits to figure it out.
  918.                 
  919.                 register long                 bcnt = 0;
  920.                 register Boolean            theBit;
  921.                 byteCount = 0;
  922.                 while (bcnt < groupLength) {
  923.                 
  924.                     NEXTBIT(theBit, glyphData->twoByteLong, glyphData->twoByteMask);
  925.                     if (theBit)
  926.                         byteCount += 2;
  927.                     else
  928.                         ++byteCount;
  929.                     
  930.                     ++bcnt;
  931.                 
  932.                 }//end while
  933.                             
  934.             }//end if
  935.  
  936.             glyphData->currByte += byteCount;            // Point to the next byte for subsequent text.
  937.             
  938.             posGroup = &(glyphData->positions[firstGlyphInGroup]);
  939.             
  940.             /* Compute the delta of the first glyph after this group  to pass to group routines */
  941.             {
  942.                 long        nextCharIndex = firstGlyphInGroup + groupLength;
  943.                 nextDelta.x = nextDelta.y = 0;                                                            // init to zero.
  944.                 if (nextCharIndex < glyphData->nChars)                                            // if not last
  945.                     if ( ! BITTST(glyphData->advanceBits, nextCharIndex) )        // and next advance bit is zero
  946.                         nextDelta = glyphData->positions[nextCharIndex];                // make it next value in array
  947.             }
  948.             
  949.             
  950.             /** Output the glyph group **/
  951.             
  952.             if (advIsOne) {
  953.                 
  954.                 theBias = AnalyzeGlyphPositions(posGroup, groupLength);
  955.                 if ((*hIEGlobals)->params.languageLevel == 1) {
  956.                 
  957.                     status = ProcessGlyphGroupPosL1(groupLength, posGroup, text8, byteCount, rdParams, 
  958.                                                                                     theBias, addToIndex);
  959.                     
  960.                 }    else {
  961.                 
  962.                     posGroup = &(glyphData->absPositions[firstGlyphInGroup]);
  963.                     theBias = AnalyzeGlyphPositions(posGroup, groupLength);
  964.                     status = ProcessGlyphGroupPosL2(hIEGlobals, groupLength, posGroup, text8, byteCount, rdParams,
  965.                                                                                     theBias, addToIndex, &nextDelta);
  966.                     
  967.                 }//end if
  968.                 
  969.                 nrequire(status, failed_ProcessGroup);
  970.                                                         
  971.             } else {                // Advance bits were zero
  972.  
  973.                 /****
  974.                     For deltas, we don't care if the first is different from group since it is
  975.                         handled by an explicit rmoveto before the ashow or kshow
  976.                 *****/
  977.                 theBias = AnalyzeGlyphPositions(posGroup + 1, groupLength - 1);
  978.  
  979.                 if ( ((*hIEGlobals)->params.languageLevel == 1) || (theBias == eAllEqual) ) {
  980.                 
  981.  
  982.                     status = ProcessGlyphGroupDelta(groupLength, posGroup, text8, byteCount, rdParams,
  983.                                                                                     theBias, addToIndex);
  984.  
  985.                 }    else {
  986.                 
  987.                     /** If they were not all equal and we are level-2 then we can use x(y)show for speed **/
  988.                 
  989.                     posGroup = &(glyphData->absPositions[firstGlyphInGroup]);
  990.                     theBias = AnalyzeGlyphPositions(posGroup, groupLength);        // reanalyze whole group this time - for use of absolute positions.
  991.                     status = ProcessGlyphGroupPosL2(hIEGlobals, groupLength, posGroup, text8, byteCount, rdParams,
  992.                                                                                         theBias, addToIndex, &nextDelta);
  993.                 
  994.                 }//end if
  995.                                                                                     
  996.                 nrequire(status, failed_ProcessGroup); 
  997.                         
  998.             }//end if
  999.             
  1000.             advIsOne = currAdv;
  1001.             firstGlyphInGroup += groupLength;
  1002.                 
  1003.         }//end while
  1004.         
  1005.         
  1006.         glyphData->advLong = advLong;                // Save last values for next style run.
  1007.         glyphData->advMask = advMask;
  1008.         
  1009. failed_ProcessGroup:
  1010. failed_Font:
  1011.  
  1012.         return(status);    
  1013.         
  1014.     }//ProcessStyleRun
  1015.  
  1016.  
  1017.  
  1018.  
  1019. //<FF>
  1020. /******************************************
  1021.     GlyphPrimitive:
  1022.     
  1023.     Translate a glyph shape to PostScript.
  1024.     
  1025. *******************************************/
  1026. OSErr _GlyphPrimitive(TIEGlobalsHdl hIEGlobals, gxShape theShape, TgeometryOptions geomOptions)
  1027.     {
  1028. #pragma unused(geomOptions)
  1029.         OSErr                        status;
  1030.         TGlyphDataRec        glyphData;                    // Block o'glyph data.
  1031.         long                        currGlyph;                    // Index of glyph we are currently processing.
  1032.         long                        styleIndex;                    // Index of style we are currently processing.
  1033.         gxPoint*                pTangent;                        // Pointer into tangent vectors.
  1034.         gxStyle*                pStyle;                            // Pointer into styles array.
  1035.         short                        *pRunSize;                    // size of current style run.
  1036.         short                        tanRunSize;                    // size of run of tangenets.
  1037.         short                        nGlyphsDone;                // Number of glyphs done so far in style run.
  1038.         short                        remaining;                    // Number of glyphs remaining in run.
  1039.         short                        stackLimit;                    // Usable stack limit for glyph shapes.
  1040.         long                        addToIndex = 0;            // Add to res index for hex
  1041.                 
  1042.         if ((*hIEGlobals)->params.renderOptions & gxNeedsHexOption)
  1043.             addToIndex = kAddForHexText;
  1044.         
  1045.         
  1046.         
  1047.         /******
  1048.             Usable stack space for glyph shapes (positions for glyphs are potentially put on stack)
  1049.             Evil Heuristic:
  1050.             
  1051.             take real stack limit divided by 2 because we need to push x,y
  1052.             subtract 50 to allow for any procedures that may be executed due
  1053.             to text face, etc…
  1054.         *******/
  1055.         stackLimit = ( (*hIEGlobals)->params.opStackLimit >> 1 ) - 50;
  1056.         ncheck((stackLimit < 0));
  1057.         
  1058.         
  1059.         /** Set up the work space for processing the glyphs **/
  1060.  
  1061.         status = GlyphDataIntoWorkSpace(hIEGlobals, theShape, &glyphData);
  1062.         nrequire(status, failed_GetGlypData);
  1063.         
  1064.         glyphData.advLong = glyphData.advanceBits;                // Get first long full o'advances.
  1065.         glyphData.advMask = 0x80000000;                                        // Initialize the advance bit mask.
  1066.         glyphData.twoByteLong = glyphData.fhUserData;            // Get first long full o'two byte flags.
  1067.         glyphData.twoByteMask = 0x80000000;                                // Initialize mask to two-byte bits.
  1068.         glyphData.currByte = glyphData.glyphs;                        // Point to first glyph in shape.
  1069.         currGlyph = 0;                                                                        // Initialize glyph index.
  1070.         
  1071.         /**********************************************
  1072.             The first advance bit will always be 1, because
  1073.             we need at least one position for the glyph shape.
  1074.             Check the 2nd advance bit.  If it is 0 and the delta
  1075.             is 0, then do a moveto now for the first position and
  1076.             reset the 1st advance bit to be 0.  This Eliminates
  1077.             having the first glyph group being an absolute poistioned
  1078.             single character which is a dumb thing to have.
  1079.             
  1080.         ************************************************/    
  1081.         if ( ((*(glyphData.advLong) & 0x40000000) == 0) && (glyphData.nChars > 1) ) {
  1082.         
  1083.             status = DoMoveto((*hIEGlobals)->pRDParams, glyphData.positions);
  1084.             nrequire(status, failed_DoMoveto);
  1085.             
  1086.             *(glyphData.advLong) &= 0x7FFFFFFF;                // Clear the first advance bit        
  1087.             glyphData.positions[0].x = 0;                            // Set first delta to be 0,0
  1088.             glyphData.positions[0].y = 0;
  1089.         
  1090.         }//end if
  1091.         
  1092.                                 
  1093.         /*** 
  1094.             Process Each of the style runs: 
  1095.             Within each style run, find runs of
  1096.             equal tangent vectors and process seperately
  1097.         ***/
  1098.         pRunSize = glyphData.runs;
  1099.         pTangent = glyphData.tangents;
  1100.         pStyle = glyphData.styles;
  1101.         
  1102.         for (styleIndex = 0; styleIndex < glyphData.nStyles; styleIndex++) {
  1103.             
  1104.             nGlyphsDone = 0;
  1105.             remaining = *pRunSize;
  1106.             
  1107.             while (nGlyphsDone < *pRunSize) {
  1108.             
  1109.                 tanRunSize = 1;
  1110.                 while ( (pTangent->x == (pTangent + 1)->x ) && 
  1111.                                 (pTangent->y == (pTangent + 1)->y ) &&
  1112.                                 (tanRunSize < remaining) && 
  1113.                                 (tanRunSize < stackLimit) ) {
  1114.                 
  1115.                     ++pTangent;
  1116.                     ++tanRunSize;
  1117.                 
  1118.                 }//end while
  1119.                     
  1120.                 status = ProcessStyleRun(hIEGlobals, currGlyph, *pStyle, &glyphData, tanRunSize, pTangent,
  1121.                                                                         addToIndex);
  1122.                 nrequire(status, failed_ProcssRun);
  1123.     
  1124.                 ++pTangent;                                                        // Move to next tangent.
  1125.                 nGlyphsDone += tanRunSize;                
  1126.                 currGlyph += tanRunSize;
  1127.                 remaining -= tanRunSize;
  1128.                 
  1129.             }//end while
  1130.             
  1131.             ++pStyle;
  1132.             ++pRunSize;            
  1133.         
  1134.         }//end for
  1135.  
  1136.  
  1137.  
  1138. failed_ProcssRun:
  1139.  
  1140. failed_DoMoveto:
  1141.  
  1142.         /** Release the work space **/
  1143.         {
  1144.             register OSErr saveStatus = PSReleaseWorkSpace(hIEGlobals);
  1145.             ncheck(saveStatus);
  1146.             if (status == noErr)
  1147.                 status = saveStatus;
  1148.                 
  1149.         }
  1150.  
  1151. failed_GetGlypData:
  1152.  
  1153.         return(status);
  1154.         
  1155.     }//GlyphPrimitive
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167. //<FF>
  1168. /******************************************
  1169.     TextPrimitive:
  1170.     
  1171.     Translate a text shape to PostScript.
  1172.     
  1173. *******************************************/
  1174. OSErr _TextPrimitive(TIEGlobalsHdl hIEGlobals, gxShape theShape, TgeometryOptions geomOptions)
  1175.     {
  1176.         OSErr                            status;
  1177.         gxStyle                        theStyle;
  1178.         long                            byteCnt;                // How many bytes of text.
  1179.         char                            *pText;                    // Pointer to the text.
  1180.         gxPoint                        textLoc;                // Where to draw it.
  1181.         TIEGlobalsPtr            pGlobals;
  1182.         TRDParams*                pRDParams;
  1183.         gxPoint                        tangent = {ff(1), ff(0)};                // text always has 1 0 tangent vector.
  1184.         gxTag                            textTag;                                                // tag where modified char codes are stored.
  1185.         long                            addToIndex = 0;                                    // Add to res index for hex
  1186.         
  1187.         if ( GXGetText(theShape, nil, nil, nil) == 0)            // see if we have to do anything?
  1188.             return(noErr);
  1189.         
  1190.         /** Size > 0, process the text **/
  1191.  
  1192.         theStyle = GXGetShapeStyle(theShape);
  1193.  
  1194.         /** If the style is vertical, we must convert it to a glyph shape and process it that way **/
  1195.  
  1196.         if (GXGetStyleTextAttributes(theStyle) & gxVerticalText) {
  1197.             
  1198.             gxShape                    workShape;
  1199.         
  1200.             /* If the shape is shared, work on the copy */
  1201.             
  1202.             if (GXGetShapeOwners(theShape) > 1) {
  1203.             
  1204.                 workShape = GXCopyToShape(nil, theShape);
  1205.                 nrequire(status = GXGetGraphicsError(nil), failed_copyIt);
  1206.                 
  1207.             } else {
  1208.             
  1209.                 workShape = theShape;
  1210.                 
  1211.             }//end if
  1212.             
  1213.             GXSetShapeType(workShape, gxGlyphType);
  1214.             nrequire(status = GXGetGraphicsError(nil), failed_SetShapeType);
  1215.             
  1216.             /* Process the glyph shape */
  1217.             
  1218.             status = _GlyphPrimitive(hIEGlobals, workShape, geomOptions);
  1219.             nrequire(status, failed_GlyphPrimitive);
  1220.             
  1221.             /* dispose of the working copy if necessary */
  1222.             if (workShape != theShape)
  1223.                 GXDisposeShape(workShape);
  1224.         
  1225.         } else {
  1226.         
  1227.             /* Process the text shape */
  1228.         
  1229.             if ((*hIEGlobals)->params.renderOptions & gxNeedsHexOption)
  1230.                 addToIndex = kAddForHexText;
  1231.             
  1232.             pGlobals = *hIEGlobals;
  1233.             pRDParams = pGlobals->pRDParams;                        // Grab the parameter block for ResPrintf.
  1234.             
  1235.             
  1236.             GXGetText(theShape, nil, nil, &textLoc);            // Get the text shape's position.
  1237.             
  1238.             /** Get the text data from the tag created by the Font Handler **/
  1239.     
  1240.             GXGetShapeTags(theShape, fhTextDataTag, 1, 1, &textTag);
  1241.             ncheck(GXGetGraphicsError(nil));
  1242.             GXLockTag(textTag);
  1243.             pText = (char*)((char*)GXGetTagStructure(textTag, &byteCnt) - tagStructureBugOffset);
  1244.                     
  1245.             /** Set the font in the current graphics state **/
  1246.     
  1247.             nrequire(status = _TextStylePrimitive(hIEGlobals, theStyle, &tangent), failed_Font);
  1248.             
  1249.             /** If the style is not left justified, adjust it’s position here **/
  1250.             if( GXGetStyleJustification(theStyle) != gxLeftJustify ) {
  1251.                     long count = GXGetGlyphMetrics(theShape, nil, nil, nil);
  1252.                     gxPoint *positions;
  1253.  
  1254.                     status = PrNewPtr((Ptr*)&positions, (count + 1) * sizeof(gxPoint));
  1255.                     nrequire(status, failed_NewPtr);
  1256.                     GXGetGlyphMetrics(theShape, positions, nil, nil);
  1257.                     textLoc = positions[0];
  1258.                     DisposePtr( (Ptr)positions );
  1259.             }
  1260.  
  1261.             /* Move the current point for the shape. */
  1262.  
  1263.             nrequire(status = DoMoveto(pRDParams, &textLoc), failed_Moveto);
  1264.             
  1265.             /** Do the show **/        
  1266.             
  1267.             pRDParams->resIndex = kShow + addToIndex;
  1268.             nrequire(status = RDResPrintf(pRDParams, pText, byteCnt), failed_Show);
  1269.             
  1270. failed_Show:        
  1271. failed_NewPtr:
  1272. failed_Moveto:        
  1273. failed_Font:
  1274.         
  1275.             GXUnlockTag(textTag);
  1276.  
  1277.         }//end if
  1278.                 
  1279.  
  1280.  
  1281.         if (status == noErr)        
  1282.             status = GXGetGraphicsError(nil);
  1283.     
  1284.         ncheck(status);
  1285.  
  1286. failed_GlyphPrimitive:
  1287. failed_SetShapeType:
  1288. failed_copyIt:    
  1289.         return(status);
  1290.     
  1291.     }//TextPrimitive
  1292.